package com.ywdnf.javaruntimecompile.core.service.impl;

import com.ywdnf.javaruntimecompile.App;
import com.ywdnf.javaruntimecompile.core.FunInterface;
import com.ywdnf.javaruntimecompile.core.service.RuntimeCompileService;
import com.ywdnf.javaruntimecompile.fileobject.JavaSourceFromString;
import com.ywdnf.javaruntimecompile.model.Result;
import com.ywdnf.javaruntimecompile.util.ResultUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import org.springframework.stereotype.Service;

/**
 * 实现
 *
 * @author lss
 * @date 2019-05-09, Thu
 */
@Service
public class RuntimeCompileServiceImpl implements RuntimeCompileService {

  /**
   * target路径
   */
  private static final String CLASS_PATH = App.class.getResource("").getPath();

  /**
   * 系统Java编译器
   */
  private static JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

  /**
   * Java对象文件管理
   */
  private static StandardJavaFileManager fileManager;

  /**
   * 临时结果输出文件
   */
  private static File file = new File("output.txt");

  /**
   * 临时生成的字节码文件名前缀
   */
  private static final String TEMP_FILE_PREFIX = "TempFun";


  static {
    fileManager = javaCompiler.getStandardFileManager(null, null, null);
    try {
      fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList(new File(CLASS_PATH)));
    } catch (IOException ignored) {
    }
  }

  @SuppressWarnings("ResultOfMethodCallIgnored")
  @Override
  public Result compileAndGetResult(String javaCode) throws IOException {

    PrintStream p;
    if (file.exists()) {
      file.delete();
    }
    file.createNewFile();
    p = new PrintStream(file);

    String sourceCodeBuilder = "import com.ywdnf.javaruntimecompile.core.FunInterface;\n"
        + "public class TempFun implements FunInterface {\n\n"
        + "  @Override\n"
        + "  public void displaySimple() {\n"
        + "    "
        + javaCode
        + "    \n"
        + "  }\n"
        + "}";
    System.out.println(sourceCodeBuilder);
    // 将标准输定向到文件
    System.setOut(p);
    System.setErr(p);
    JavaFileObject jfo = new JavaSourceFromString(TEMP_FILE_PREFIX, sourceCodeBuilder);
    boolean compileSuccess = javaCompiler
        .getTask(null, fileManager, null, null, null, Collections.singletonList(jfo))
        .call();
    if (compileSuccess) {
      // 编译成功
      try {
        URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL("file:" + CLASS_PATH)});
        FunInterface tempFun = (FunInterface) classLoader.loadClass(TEMP_FILE_PREFIX).newInstance();
        tempFun.displaySimple();
        File file = new File(CLASS_PATH + TEMP_FILE_PREFIX + ".class");
        if (file.exists()) {
          file.delete();
        }
      } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | MalformedURLException e) {
        e.printStackTrace();
        return ResultUtils.newFailedResult("异常 " + e.getMessage());
      }
    }
    File res = new File("output.txt");
    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(res
    )));
    StringBuilder builder = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
      builder.append(line).append("\n");
    }
    return compileSuccess
        ? ResultUtils.newSuccessfulResult(builder.toString(), null)
        : ResultUtils.newFailedResult(builder.toString());
  }

}
